package gnss

import (
	"bytes"
	"dgo/goutils/utils"
	"encoding/binary"
	"fmt"
	"time"
)

/*
*

	低轨卫星星历
*/
type UnicoreMsg8029Wlnav struct {

	// 2017年1月1日0点0分0秒为起点
	Week        uint16
	Tow         uint32
	Prn         uint16
	SigType     uint16 // 1：L1 14：L5
	ChanelNum   uint32
	SubFrameNum uint32
	Crc         uint32
	Data        utils.BytesBuilder
}

func (this *UnicoreMsg8029Wlnav) GPSTime() time.Time {
	return TOW2TimeEx(uint(this.Week), uint(this.Tow))
}

/*
*
和芯王总:
研发给回复解释了下，   比如L1有30个字。对于每一个字，共4个字节，ASCII输出时按照这样的原则。我会先读高位的字节，即24到31bit的值，然后是16到23bit的值，之后是8到15bit的值，最后是0到7bit的值
*/
func (this *UnicoreMsg8029Wlnav) DataBuf() []byte {
	dataBuf := this.Data.Bytes()
	newBuf := make([]byte, 0, len(dataBuf))
	r := bytes.NewReader(dataBuf)
	buf0 := make([]byte, 4)
	for {
		n, err := r.Read(buf0)
		if err != nil {
			break
		}
		buf0 = utils.SwapBytes(buf0[:n])
		newBuf = append(newBuf, buf0...)
	}
	return newBuf
}

func (this *UnicoreMsg8029Wlnav) DataAsciiString() string {
	return utils.BufToHexStr(this.DataBuf(), 0, "")
}

func (this *UnicoreMsg8029Wlnav) OutputFmtStyleWl() string {
	var sb utils.BytesBuilder
	sb.Appendf("[%s] %.3d", utils.DateTimeString3(this.GPSTime()), this.Prn)
	if this.SigType == 1 {
		sb.AppendStr(" CL1 CNAV1")
	} else if this.SigType == 14 {
		sb.AppendStr(" CL5 CNAV2")
	} else {
		sb.AppendStrPrefixForWidth(fmt.Sprintf("%d", this.SigType), 10, " ")
	}
	sb.AppendStrPrefixForWidth(fmt.Sprintf("%d ", this.SubFrameNum), 5, " ")
	sb.AppendStrPrefixForWidth(fmt.Sprintf("%d ", this.Week-1930), 10, " ")
	sb.AppendStrPrefixForWidth(fmt.Sprintf("%d ", this.Tow/1000), 10, " ")
	sb.AppendStr(this.DataAsciiString())
	return sb.String()
}

func (this *UnicoreMsg8029Wlnav) DecodePackageBuf(packBuf []byte) error {
	this.Week = binary.LittleEndian.Uint16(packBuf[10:])
	this.Tow = binary.LittleEndian.Uint32(packBuf[12:])

	if packBuf[8] == 0 { // 0:GPS时间

	}

	bodyBuf := packBuf[24:]
	bodyl := len(bodyBuf)
	this.Crc = binary.LittleEndian.Uint32(bodyBuf[bodyl-4:])
	crc0 := Crc32(packBuf[:len(packBuf)-4])
	if this.Crc != crc0 {
		return fmt.Errorf("CRC校验异常")
	}

	this.Prn = binary.LittleEndian.Uint16(bodyBuf[:])
	this.SigType = binary.LittleEndian.Uint16(bodyBuf[2:])
	this.ChanelNum = binary.LittleEndian.Uint32(bodyBuf[4:])
	this.SubFrameNum = binary.LittleEndian.Uint32(bodyBuf[8:])
	this.Data.Write(bodyBuf[12 : bodyl-4])
	return nil
}
